# manager.py
import threading
import time
import os
import json
from typing import List
import os.path
import tkinter.messagebox as messagebox

from code.config import CleanerConfig
from code.cleaners import SmartDuplicateCleaner, PackageCleaner

class CleanManager:
    """清理管理器，协调不同类型的清理器"""
    
    def __init__(self, system_type: str = None, clean_dirs: List[str] = None, 
                 link_type: str = 'delete', full_scan: bool = False,
                 hash_algorithm: str = 'md5',fast_mode: bool = False):
        self.config = CleanerConfig(system_type, clean_dirs, 
                                    link_type, 
                                    full_scan,fast_mode,
                                    hash_algorithm=hash_algorithm)
        self.cleaners = {
            'duplicate': SmartDuplicateCleaner(self.config),
            'package': PackageCleaner(self.config)
        }
        self.pause_event = threading.Event()  # 用于暂停扫描
        self.scan_data = {}
        self.stop_event = threading.Event()  # 用于停止所有扫描
        self.cache_dir = None  # 缓存目录
    
    def run_scan(self, clean_types: List[str], progress_callback=None, log_callback=None):
        """执行扫描，支持进度回调和中途停止"""
        import time
        start = time.perf_counter()
        if not self.config.target_dirs:
            print("⚠️ 警告：即将进行全盘扫描！")
            print("可能需要管理员权限且耗时较长")
            # 使用messagebox替代input
            if not messagebox.askyesno("全盘扫描确认", "全盘扫描会检查系统所有驱动器，可能需要较长时间并需要管理员权限。是否继续？"):
                return
            
        self.stop_event.clear()
        # 设置缓存目录
        self.cache_dir = os.path.join(self.config.get_cache_dir(), ".cleaner_cache")
        os.makedirs(self.cache_dir, exist_ok=True)
        
        # 检查是否有未完成的扫描
        if self._check_resume_scan(clean_types):
            return
        
            
        # 将目标目录设置给每个清理器的配置
        for cleaner in self.cleaners.values():
            if hasattr(cleaner, 'config'):
                cleaner.config.set_target_dirs(self.config.target_dirs)

        self.pause_event.clear()
        total_steps = len(clean_types)
        
        for i, clean_type in enumerate(clean_types):
            if self.stop_event.is_set():
                return
                
            # 检查暂停状态
            while self.pause_event.is_set() and not self.stop_event.is_set():
                time.sleep(0.5)
                
            if clean_type not in self.cleaners:
                continue
                
            cleaner = self.cleaners[clean_type]
            
            # 设置日志回调
            if hasattr(cleaner, 'set_log_callback') and log_callback:
                cleaner.set_log_callback(log_callback)
            
            # 为每个清理器创建进度回调
            def sub_progress_callback(progress):
                if progress_callback:
                    base_progress = i / total_steps * 100
                    step_progress = progress / total_steps
                    progress_callback(base_progress + step_progress)
            
            try:
                # 传递进度回调和停止事件给具体的扫描器
                files = cleaner.scan(progress_callback=sub_progress_callback)
                if self.stop_event.is_set():
                    return
                    
                result = cleaner.save_scan_results(clean_type)
                # 构建结果文件的保存路径
                saved_path = os.path.join(self.cache_dir, f"{clean_type}_{result['timestamp']}.json")
                # 使用缓存目录保存扫描结果
                with open(saved_path, 'w', encoding='utf-8') as f:
                    json.dump(result, f, indent=2, ensure_ascii=False)
                    
                self.scan_data[clean_type] = saved_path
                
                if clean_type == 'package':
                    # 软件包扫描结果是字典列表，提取'path'键
                    total_size = sum(f['size'] for f in files if 'path' in f and os.path.exists(f['path'])) if files else 0
                else:
                    # 重复文件扫描结果是路径列表
                    total_size = sum(os.path.getsize(f) for f in files if os.path.exists(f)) if files else 0
                if log_callback:
                    log_callback(f"\n✅ {clean_type} 扫描完成")
                    log_callback(f"发现 {len(files)} 个可清理项")
                    log_callback(f"预计可释放空间: {total_size/1024/1024:.2f} MB")
                    log_callback(f"扫描结果已保存至: {saved_path}\n")
                
            except Exception as e:
                error_msg = f"💥 {clean_type} 扫描器错误: {str(e)}"
                print(error_msg)
                if log_callback:
                    log_callback(error_msg)
            
            # 更新总体进度
            # 清理该清理器的状态文件
            state_file = os.path.join(self.cache_dir, f"{clean_type}_state.json")
            if os.path.exists(state_file):
                os.remove(state_file)
                
            if progress_callback and not self.stop_event.is_set():
                progress = (i + 1) / total_steps * 100
                progress_callback(progress)
            
            end = time.perf_counter()
            print(f"总耗时: {end - start:.2f}秒")
    
    def _check_resume_scan(self, clean_types) -> bool:
        """检查并恢复未完成的扫描"""
        state_files = [f for f in os.listdir(self.cache_dir) if f.endswith("_state.json")]
        if not state_files:
            return False
            
        # 询问用户是否恢复
        if not messagebox.askyesno("发现未完成扫描", "检测到未完成的扫描任务，是否继续?"):
            # 用户选择不恢复，删除状态文件
            for f in state_files:
                os.remove(os.path.join(self.cache_dir, f))
            return False
        
        # 设置每个清理器的状态文件
        for clean_type in clean_types:
            state_file = os.path.join(self.cache_dir, f"{clean_type}_state.json")
            if os.path.exists(state_file):
                cleaner = self.cleaners[clean_type]
                if hasattr(cleaner, 'cache_dir'):
                    cleaner.cache_dir = self.cache_dir
                    print(f"恢复 {clean_type} 扫描器状态")
        
        return True
        
    def run_clean(self, clean_types: List[str]) -> int:
        """执行清理操作"""
        cleaned_count = 0
        
        # 确认对话框
        if not messagebox.askyesno("确认清理", "确定要删除选中的文件吗？此操作不可恢复！"):
            return 0
            
        for clean_type in clean_types:
            if clean_type not in self.cleaners:
                continue
                
            cleaner = self.cleaners[clean_type]
            try:
                # 针对软件包清理器，处理包含文件信息的字典列表
               if clean_type == 'package' and isinstance(cleaner.scan_results, list):
                   for item in cleaner.scan_results:
                       file_path = item.get('path', '')
                       if isinstance(file_path, str) and os.path.exists(file_path):
                           try:
                               if os.path.isfile(file_path):
                                   os.remove(file_path)
                                   cleaned_count += 1
                               elif os.path.isdir(file_path):
                                   import shutil
                                   shutil.rmtree(file_path)
                                   cleaned_count += 1
                           except Exception as e:
                               error_msg = f"无法删除 {file_path}: {e}"
                               print(error_msg)
               else:
                   count = cleaner.clean()
                   cleaned_count += count
               print(f"✅ {clean_type} 清理完成，已清理 {cleaned_count} 个项目")  # 统一使用cleaned_count
            except Exception as e:
                error_msg = f"💥 {clean_type} 清理器错误: {str(e)}"
                print(error_msg)
                
        return cleaned_count
    
    def stop_scan(self):
        """停止所有正在进行的扫描"""
        self.stop_event.set()
        for cleaner in self.cleaners.values():
            if hasattr(cleaner, 'stop'):
                cleaner.stop()
    
    def pause_scan(self):
        """暂停扫描"""
        self.pause_event.set()
        for cleaner in self.cleaners.values():
            if hasattr(cleaner, 'pause_scan'):
                cleaner.pause_scan()
    
    def resume_scan(self):
        """继续扫描"""
        self.pause_event.clear()
        for cleaner in self.cleaners.values():
            if hasattr(cleaner, 'resume_scan'):
                cleaner.resume_scan()